import stub.GDispatcherStub;
import stub.PDispatcherStub;


public class StubMain {

	/**
	 * @param args
	 */
	
	public static GDispatcherStub gds;
	public static PDispatcherStub pds;
	
	public static void main(String[] args) {
		 int port=12350;
		 boolean overallResult = true;
		 boolean testResult;
		 
		 port = Integer.parseInt(args[0]);
		 
		 gds = new GDispatcherStub(port);
		 pds = new PDispatcherStub();
		 
         System.out.println("Testing GDispatcher handling functionality for happy path");
         System.out.println("------------------------------");
         System.out.println("Start an elevator pointing to port "+port);
         testResult=testGDispatcherHappyPath(port);
         overallResult &=testResult;
         System.out.println("------------------------------");
         System.out.println("Pass? "+testResult);
         System.out.println("");
         System.out.println("");

         System.out.println("Testing GDispatcher handling functionality for disconnect path");
         System.out.println("------------------------------");
         System.out.println("Start an elevator pointing to port "+port);
         testResult=testGDispatcherDisconnectPath(port);
         overallResult &=testResult;
         System.out.println("------------------------------");
         System.out.println("Pass? "+testResult);
         System.out.println("");
         System.out.println("");
         System.out.println("Testing PDispatcher handling functionality for happy path");
         System.out.println("------------------------------");
         System.out.println("Start an elevator pointing to port "+port);
         testResult=testPDispatcherHappyPath(port); 
         overallResult &=testResult;
         System.out.println("------------------------------");
         System.out.println("Pass? "+testResult);
         System.out.println("");
         System.out.println("");
         System.out.println("Testing PDispatcher handling functionality for sad path");
         System.out.println("------------------------------");
         System.out.println("Start an elevator pointing to port "+port);
         testResult=testPDispatcherSadPath(port); 
         overallResult &=testResult;
         System.out.println("------------------------------");
         System.out.println("Pass? "+testResult);
         System.out.println("");
         System.out.println("");
         
         
         System.out.println("============================================");
         System.out.println("ALL ELEVATOR TESTS PASSED? "+overallResult);
	}
	
	public static boolean testGDispatcherHappyPath(int port){
		boolean retVal=true;
		boolean testResult;
		
		byte clientId=3;
		byte numFloors = 15;
		
		testResult=gds.openSocket();
		System.out.println("Open socket Test - "+testResult);
		retVal &=testResult;
		
		testResult=gds.getRegistration();
		System.out.println("Get Registration message test - "+testResult);
		retVal &=testResult;
		
		testResult=gds.sendRegistrationReply(clientId, numFloors);
		System.out.println("Send registration reply test - "+testResult);
		retVal &=testResult;
		
		testResult=gds.pingElevator();
		System.out.println("Elevator Ping test - "+testResult);
		retVal &=testResult;

		testResult=!gds.isSocketClosed();
		System.out.println("Test Socket is still open - "+testResult);
		retVal &=testResult;

		testResult=gds.pingElevator();
		System.out.println("Elevator Ping test - "+testResult);
		retVal &=testResult;
		
		//Give some time for the client ID to propagate through the elevator
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		testResult=gds.checkId(clientId);
		System.out.println("Test the stored client ID - "+testResult);
		retVal &=testResult;

		testResult=gds.deregisterElevator();
		System.out.println("Test deregistering elevator - "+testResult);
		retVal &=testResult;

		return retVal;
	}
	
 	public static boolean testGDispatcherDisconnectPath(int port){
		boolean retVal=true;
		boolean testResult;
		
		byte clientId=3;
		byte numFloors = 15;
		
		//Open the socket, should succeed
		testResult=gds.openSocket();
		System.out.println("Open socket Test - "+testResult);
		retVal &=testResult;
		
		//Go through the registration
		testResult=gds.getRegistration();
		System.out.println("Get Registration message test - "+testResult);
		retVal &=testResult;
		
		//Reply
		testResult=gds.sendRegistrationReply(clientId, numFloors);
		System.out.println("Send registration reply test - "+testResult);
		retVal &=testResult;
			
		//Ping elevator
		testResult=gds.pingElevator();
		System.out.println("Elevator Ping test before disconnect - "+testResult);
		retVal &=testResult;

	    //Close the socket
		gds.closeSocket();
		testResult=gds.isSocketClosed();
		System.out.println("Close socket test - "+testResult);
		retVal &=testResult;
	
	    //Reopen socket
		gds.openSocket();
		testResult=!gds.isSocketClosed();
	    System.out.println("Reopen socket test - "+testResult);
		retVal &=testResult;
	    
	    //Re-register with elevator
		testResult=gds.getRegistration();
		System.out.println("Get Registration message 2 test - "+testResult);
		retVal &=testResult;
		
		//Reply
		testResult=gds.sendRegistrationReply(clientId, numFloors);
		System.out.println("Send registration reply 2 test - "+testResult);
		retVal &=testResult;
			
		//Ping elevator
		testResult=gds.pingElevator();
		System.out.println("Elevator Ping test after disconnect - "+testResult);
		retVal &=testResult;
		//Close the elevator, should succeed
		testResult=gds.deregisterElevator();
		System.out.println("Test deregistering elevator - "+testResult);
		retVal &=testResult;
		
		return retVal;
 	}
 
 	public static boolean testPDispatcherHappyPath(int port){
 		boolean retVal=true;
		boolean testResult;
		
		byte clientId=3;
		byte numFloors = 15;
		
		testResult=gds.openSocket();
		System.out.println("Open socket Test - "+testResult);
		retVal &=testResult;
		
		testResult=gds.getRegistration();
		System.out.println("Get Registration message test - "+testResult);
		retVal &=testResult;
		
		testResult=gds.sendRegistrationReply(clientId, numFloors);
		System.out.println("Send registration reply test - "+testResult);
		retVal &=testResult;

		//GDispatcher is now connected, and I can get PDispatcher connected	
		//Wait until the udp port is available
		int udpPort=0;
		while (udpPort==0){
			udpPort=gds.getElevatorUDPPort();
		}
		
		pds.startSocket(gds.getElevatorAddress(), udpPort);
		
		//Test each floor button
		for (byte floor = 0;floor<numFloors;floor++){
			int buttonResult =pds.sendButtonPress(floor);
			testResult = (buttonResult == 1);
			System.out.println("Send button press "+ floor +" test - "+testResult);
			retVal &= testResult;
		}

		//In
		testResult = (pds.sendPersonTransfer(5,(byte)1)==1);
		System.out.println("Send person transfer in test - "+testResult);
		retVal &= testResult;
   
		testResult = (pds.sendPersonInElevator()==1);
		System.out.println("Send person in elevator test - "+testResult);
		retVal &= testResult;

		//out
		testResult = (pds.sendPersonTransfer(5,(byte)0)==1);
		System.out.println("Send person transfer out test - "+testResult);
		retVal &= testResult;
   
		testResult = (pds.sendPersonOutElevator()==1);
		System.out.println("Send person out elevator test - "+testResult);
		retVal &= testResult;
		
		
		System.out.println("Elevator Ping test - "+testResult);
		retVal &=testResult;
	
		//End the elevator via GDispatcher
		testResult=gds.deregisterElevator();
		System.out.println("Test deregistering elevator - "+testResult);
		retVal &=testResult;
		
		//Close the pdispatcher socket
		pds.endSocket();

		return retVal;		
 	}
 	
 	public static boolean testPDispatcherSadPath(int port){
 		boolean retVal=true;
		boolean testResult;
		
		byte clientId=3;
		byte numFloors = 15;
		
		testResult=gds.openSocket();
		System.out.println("Open socket Test - "+testResult);
		retVal &=testResult;
		
		testResult=gds.getRegistration();
		System.out.println("Get Registration message test - "+testResult);
		retVal &=testResult;
		
		testResult=gds.sendRegistrationReply(clientId, numFloors);
		System.out.println("Send registration reply test - "+testResult);
		retVal &=testResult;

		//GDispatcher is now connected, and I can get PDispatcher connected	
		//Wait until the udp port is available
		int udpPort=0;
		while (udpPort==0){
			udpPort=gds.getElevatorUDPPort();
		}
		
		pds.startSocket(gds.getElevatorAddress(), udpPort);
		
		//Test a range of floors that are invalid
		for (byte floor = (byte) (numFloors+1);floor<numFloors+10;floor++){
			int buttonResult =pds.sendButtonPress(floor);
			testResult = (buttonResult == 2); //Should respond as invalid floor
			System.out.println("Send button press "+ floor +" test (invalid floor) - "+testResult);
			retVal &= testResult;
		}

		//Test sending person transfer messages out of order
		testResult = (pds.sendPersonInElevator()==0);
		System.out.println("Send person in elevator test - "+testResult);
		retVal &= testResult;
   
		testResult = (pds.sendPersonOutElevator()==0);
		System.out.println("Send person out elevator test - "+testResult);
		retVal &= testResult;
		
		testResult = (pds.sendPersonTransfer(50,(byte)0)==0);
		System.out.println("Send person transfer out elevator test - "+testResult);
		retVal &= testResult;
		
		System.out.println("Elevator Ping test - "+testResult);
		retVal &=testResult;
	
		//End the elevator via GDispatcher
		testResult=gds.deregisterElevator();
		System.out.println("Test deregistering elevator - "+testResult);
		retVal &=testResult;

		//Close the person dispatcher sockets
		pds.endSocket();
		
		return retVal;
		
 	}
 	
}
